/****************************************************
 * Description: Controllar for 用户
 * Copyright:   Copyright (c) 2013
 * Company:     beiwaionline
 * @author      bfsu
 * @version     1.0
 * @see
	HISTORY
	*  2013-08-08 bfsu Create File
**************************************************/

package com.bfsuol.bfsuolframework.security.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bfsuol.bfsuolcomponents.log.BfsuolLogger;
import com.bfsuol.bfsuolframework.core.controller.SpringControllerSupport;
import com.bfsuol.bfsuolframework.core.controller.json.MessageJson;
import com.bfsuol.bfsuolframework.core.controller.support.Pagination;
import com.bfsuol.bfsuolframework.core.controller.support.QueryParam;
import com.bfsuol.bfsuolframework.core.exception.ValidationException;
import com.bfsuol.bfsuolframework.core.spring.QueryParameter;
import com.bfsuol.bfsuolframework.core.utils.DateTimeUtils;
import com.bfsuol.bfsuolframework.core.utils.EncryptUtils;
import com.bfsuol.bfsuolframework.core.utils.StringUtils;
import com.bfsuol.bfsuolframework.security.annotations.*;
import com.bfsuol.bfsuolframework.security.dao.BaseUser;
import com.bfsuol.bfsuolframework.security.dao.Group;
import com.bfsuol.bfsuolframework.security.dao.Role;
import com.bfsuol.bfsuolframework.security.entity.dto.GroupDTO;
import com.bfsuol.bfsuolframework.security.entity.dto.RoleDTO;
import com.bfsuol.bfsuolframework.security.service.BaseUserService;
import com.bfsuol.bfsuolframework.security.service.GroupService;
import com.bfsuol.bfsuolframework.security.service.RoleService;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.*;

@Controller
@RequestMapping("/components/security/user")
public class BaseUserController extends SpringControllerSupport {

    @Autowired
    private BaseUserService baseUserService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private GroupService groupService;
    
    @SecPrivilege(title="用户权限")
	@RequestMapping("/index")
	public ModelAndView index(Model model){

		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName(getViewNamedPath("index"));
		model.addAttribute("functions",getRoleFunctions());
		return modelAndView;
	}
	
    @SecList
	@RequestMapping("/list")
	public ModelAndView list(
			@QueryParameter("query") QueryParam query,
			@ModelAttribute("page") Pagination page,
			Model model){
		model.addAttribute("functions",getRoleFunctions());

		com.baomidou.mybatisplus.extension.plugins.pagination.Page page1 = new Page(page.getDefaultCurrentPage(),page.getPageSize());
		com.baomidou.mybatisplus.extension.plugins.pagination.Page baseUserPages = baseUserService.page(page1,new QueryWrapper<>());
		page.setItems(baseUserPages.getRecords());
		page.setTotalRecord((int) baseUserPages.getTotal());

		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName(getViewNamedPath("list"));
		return modelAndView;
	}
	
    @SecCreate
	@RequestMapping("/input")
	public ModelAndView create(@ModelAttribute BaseUser user, Model model){
		List<Group> groups = new ArrayList<Group>();
		groups = groupService.findAllIsEnabledGroup();
		model.addAttribute("groups", groups);

		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName(getViewNamedPath("input"));
		return modelAndView;
	}
	
    
	@RequestMapping("/input/{id}")
	public ModelAndView edit(@PathVariable("id") Long id, Model model){
		BaseUser user = baseUserService.getById(id);
		model.addAttribute("u",user);

		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName(getViewNamedPath("input"));
		return modelAndView;
	}
	
	/**
	 * 添加用户
	 * 
	 * @param user
	 * @return
	 */
	@SecCreate
	@SecEdit
	@RequestMapping("/save")
	public @ResponseBody
	MessageJson save(@ModelAttribute BaseUser user,
			@RequestParam(value = "ids", required = false) String[] ids) {

		if (StringUtils.isBlank(user.getUserName())) {// 验证用户名是否填写
			throw new ValidationException("请填写用户名！");
		}
		if (StringUtils.isBlank(user.getLoginName())) {// 验证登录名是否填写
			throw new ValidationException("请填写登录名！");
		}
		Boolean checkLoginName = baseUserService.checkLoginName(
				user.getLoginName(), user.getId());
		if (checkLoginName) { // 验证用户名的唯一性
			throw new ValidationException("用户名已存在！");
		}
		if (StringUtils.isBlank(user.getEmail())) {// 验证邮箱是否填写
			throw new ValidationException("请填写邮箱！");
		}
		Boolean checkEmail = baseUserService.checkEmail(user.getEmail(),
				user.getId());
		if (checkEmail) { // 验证邮箱的唯一性
			throw new ValidationException("邮箱已存在！");
		}

		if (user.isNew()) {
			if (StringUtils.isBlank(user.getPassword())) {// 验证密码是否填写
				throw new ValidationException("请填写密码！");
			}
			if (ids == null || ids.length < 1) {// 验证用户组是否添加
				throw new ValidationException("请选择要添加的用户组");
			}

			for (String id : ids) {
				Group group = groupService.getById(Long.valueOf(id));
				if (group == null) {
					throw new ValidationException("保存用户组时，查不到用户组id：" + id);
				}
				user.addGroup(group);
			}

			user.setUserName(user.getUserName());
			user.setLoginName(user.getLoginName());
			user.setPassword(EncryptUtils.MD5Encode(user.getPassword()));
			user.setEmail(user.getEmail());
			user.setRegisterDate(DateTimeUtils.getCurrentDate());
			user.setCreateTime(new Date());
			if(null != this.getLoginInfo())
			{
				user.setCreateUserId(this.getLoginInfo().getUserId());
				user.setCreateUserName(this.getLoginInfo().getUserName());
			}
			baseUserService.save(user);

		} else {
			BaseUser bu = new BaseUser();
			bu = baseUserService.getById(user.getId());
			bu.setUserName(user.getUserName());
			bu.setLoginName(user.getLoginName());
			if (!StringUtils.isBlank(user.getPassword())) {// 如果没有填写密码 则不修改
				bu.setPassword(EncryptUtils.MD5Encode(user.getPassword()));
			}
			if(null != this.getLoginInfo())
			{
				user.setUpdateUserId(this.getLoginInfo().getUserId());
				user.setUpdateUserName(this.getLoginInfo().getUserName());
			}
			
			bu.setEmail(user.getEmail());
			bu.setUserType(user.getUserType());
			baseUserService.updateById(bu);
		}
		// 设置更新用户权限后刷新菜单缓存
		//SecurityContext.reloadRoleMenusFromDB();
		return MessageJson.information("保存成功");
	}
	
	/**
	 * 角色设置列表
	 * @param model
	 * @return
	 */
	@SecFunction(title="角色设置",code="roleList")
	@RequestMapping("/roleinput/{id}")
	public ModelAndView roleList(@PathVariable("id") Long id,Model model){
		List<RoleDTO> roles = new ArrayList<RoleDTO>();
		String message = null;
		BaseUser bu =  new BaseUser();
		if(id==null){// 判断id是否为空
			message = "获取不到该账户的ID";
		}else{
			bu = baseUserService.getById(id);
		}
		
		if(bu.getGroups()==null||bu.getGroups().size()<1){// 判断用户是否分配了组
			message = "该账户没有分配用户组";
		}
		
		if(StringUtils.isBlank(message)){
			roles = baseUserService.canChooseRoleList(id,bu.getGroups());
		}
		//String[] ids=new String[200];
		Long[] ids=new Long[200];
		Collection<Role> roles2 = Optional.ofNullable(bu.getRoles()).orElse(Lists.newArrayList());
		int i=0;
		for(Role r:roles2){
			ids[i]=r.getId();
			i++;
		}
		model.addAttribute("user", bu);
		model.addAttribute("roles", roles);
		model.addAttribute("message", message);
		model.addAttribute("ids", ids);
		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName(getViewNamedPath("roleinput"));
		return modelAndView;
	}
	
	/**
	 * 获取指定账户，可选择的角色列表
	 * @param userId
	 * @return
	 */
//	public List<RoleDTO> canChooseRoleList(Long userId, Collection<Group> groups) {
//		int i = 0;
//		List<RoleDTO> roles = new ArrayList<RoleDTO>();// 返回的用户拥有的全部角色DTO集合
//		List<Long> allDefault = new ArrayList<Long>();// 所有分组 默认的角色ID集合
//		List<Long> allChoose = new ArrayList<Long>();// 所有分组 可选择的角色ID集合
//
//		if (groups != null && groups.size() > 0) { // 数据正确性验证 大于一个分组的用户
//			for (Group group : groups) {// 获取全部roleId
//				List<Long> tempDefault = new ArrayList<Long>();
//				List<Long> tempChoose = new ArrayList<Long>();
//				for (GroupRole groupRole : group.getRoles()) {
//					// 将roleId添加到temp
//					if (groupRole.getIsDefault().intValue() == Constants.GLOBAL_YESNO_YES.intValue()) {// 该组下默认的角色id
//						tempDefault.add(groupRole.getRole().getId());
//					}
//					if (groupRole.getIsDefault().intValue() == 0 || groupRole.getIsDefault().intValue() == Constants.GLOBAL_YESNO_NO.intValue()) {// 该组下可选的角色id
//						tempChoose.add(groupRole.getRole().getId());
//					}
//
//				}
//				if (i == 0) {// 获取第一组数据
//					allDefault = tempDefault;
//					allChoose = tempChoose;
//					i++;
//				} else {// 获取不重复的role
//					allDefault.removeAll(tempDefault);
//					allDefault.addAll(tempDefault);
//
//					allChoose.removeAll(tempChoose);
//					allChoose.addAll(tempChoose);
//				}
//			}
//
//			// 去除组之间默认与可选重叠的role
//			allChoose.removeAll(allDefault);
//
//			// 根据id获取全部默认role对象
//			for (Long id : allDefault) {
//				RoleDTO roleDTO = new RoleDTO();
//				Role role = roleService.getById(id);
//				roleDTO.setRole(role);
//				roleDTO.setIsDefault(0);
//				roles.add(roleDTO);
//			}
//
//			if (userId != null) {
//				BaseUser bu = baseUserService.getById(userId);
//				// 根据id获取全部可选role对象
//				for (Long id : allChoose) {
//					RoleDTO roleDTO = new RoleDTO();
//					Role role = roleService.getById(id);
//					roleDTO.setRole(role);
//					// 从user_role表中获取已勾选role对象
//					if (bu != null && bu.getRoles() != null
//							&& bu.getRoles().size() > 0) {
//						for (Role r : bu.getRoles()) {
//							if (r.getId() == id) { // 已勾选过的角色
//								roleDTO.setIsDefault(2);
//							}
//						}
//					}
//
//					if (roleDTO.getIsDefault() == null) { // 未勾选过的角色
//						roleDTO.setIsDefault(1);
//					}
//
//					roles.add(roleDTO);
//				}
//			}
//		}
//		return roles;
//	}
	
	/**
	 * 执行增加或删除组操作
	 * @param userId 用户ID
	 * @param roleOld 修改前，已勾选的角色集合
	 * @param roleDTOList 修改后，拥有的全部角色DTO集合
	 * @return 结果
	 */
//	public String addOrDelGroup(Long userId, Collection<Role> roleOld,
//			List<RoleDTO> roleDTOList) {
//		List<Role> delRoleList = new ArrayList<Role>();// 返回 需要删除的角色集合
//		List<Long> delLong = new ArrayList<Long>(); // 获得需要删除的角色ID集合
//		List<Long> newLong = new ArrayList<Long>();// 获取新修改用户组下，可选择的角色集合
//		
//		if (roleDTOList != null && roleDTOList.size() > 0) {
//			for (RoleDTO roleDTO : roleDTOList) {// 遍历 新用户组下的 所有角色
//					newLong.add(roleDTO.getRole().getId());// 设置新的用户组，拥有的全部角色ID
//			}
//			
//			if(roleOld!=null&&roleOld.size()>0){
//				for (Role role : roleOld) {// 遍历 原已勾选角色集合
//					delLong.add(role.getId());
//				}
//			}
//			
//			// 原有已勾选角色 而新的用户组下 没有的角色集合，即需要删除的角色
//			delLong.removeAll(newLong);
//			
//			if (delLong != null && delLong.size() > 0) {
//				for (Long id : delLong) {
//					delRoleList.add(roleService.getById(id));
//				}
//			} else {
//				delRoleList = null;
//			}
//		}
//		
//		BaseUser bu = baseUserService.getById(userId);
//		
//		// 如果存在需要删除的角色关系
//		if(delRoleList!=null&&delRoleList.size()>0){
//			for(int i=0;i<delRoleList.size();i++){
//				bu.removeRole(delRoleList.get(i));
//			}
//		}
//		
//		baseUserService.update(bu);
//		
//		// 删除用户权限后刷新菜单缓存
//		SecurityContext.reloadRoleMenus();
//		
//		return "ok";
//	}
	
	/**
	 * 给用户设置角色信息
	 * @param ids
	 * @return
	 */
	@SecFunction(title="角色设置",code="roleList")
	@RequestMapping("/roletouser")
	public @ResponseBody
	MessageJson roleUser(
			@RequestParam(value = "ids") Long[] ids,
			@RequestParam(value = "userId") Long userId) {
		String message = "";
		int failCount = 0;

		if (userId == null) {
			throw new ValidationException("提交失败,获取用户ID信息失败");
		}

		message = this.addOrRemoveRole(userId); // 处理    默认角色中 存在 已勾选角色  的  状况
		if(!StringUtils.isBlank(message)){// 错误反馈
			throw new ValidationException(message);
		}
		
		BaseUser bu = baseUserService.getById(userId);
		if (ids != null && ids.length > 0) {// 添加修改用户角色信息
			for (Long roleId : ids) {
				if (roleId == null) {
					message += "所选角色Id中存在空值";
					failCount++;
				} else {
					Role role = roleService.getById(roleId);
					bu.addRole(role);
					baseUserService.updateById(bu);
				}
			}
		}
		
		// 设置更新用户权限后刷新菜单缓存
		//SecurityContext.reloadRoleMenus ();
		
		if (StringUtils.isBlank(message)) {// 验证失败信息
			return MessageJson.success("添加角色成功");
		} else {
			return MessageJson.information("提交添加申请中：成功" + (ids.length - failCount) + "个角色。" + "失败" + failCount + "个角色。原因：" + message);
		}
	}
	
	/**
	 * 处理    默认角色中 存在 已勾选角色  的  状况
	 * @param userId
	 * @return
	 */
	public String addOrRemoveRole(Long userId){
		if(userId==null){
			return "获取用户ID失败";
		}
		BaseUser bu = baseUserService.getById(userId);
		if(bu==null){
			return "获取用户信息失败";
		}
		if(bu.getGroups()==null || bu.getGroups().size()<1){
			return null;
		}
		if(bu.getRoles()==null || bu.getRoles().size()<1){
			return null;
		}
		
		List<Role> roles = new ArrayList<Role>(); // 需要返回的角色
		List<RoleDTO> roleDTOList = baseUserService.canChooseRoleList(userId, bu.getGroups());
		for(RoleDTO dto:roleDTOList){
			if(dto.getIsDefault().intValue()==0){// 默认的角色
				for(Role role:bu.getRoles()){
					if(dto.getRole().getId().intValue()==role.getId().intValue()){// 勾选的角色在默认角色中已存在
						roles.add(role);
					}
				}
			}
		}
		String message = this.removeRole(userId);
		if(!StringUtils.isBlank(message)){
			return message;
		}
		if(roles==null || roles.size()<1){
			return null;
		}
		
		
		
		for(Role role:roles){
			bu.addRole(role);
			baseUserService.updateById(bu);
		}
		return null;
	}
	
	@RequestMapping("/changeStatus/{status}/{id}")
	public @ResponseBody  MessageJson changeStatus(@PathVariable("status") Integer status,@PathVariable("id") Long id) {
		BaseUser bu = baseUserService.getById(id);
		if(bu.getLoginName().equals(this.getLoginInfo().getLoginName())){
				return MessageJson.fail("不能更改现在登陆的账号状态");
			}else{
				baseUserService.changeStatus(id,status);	
				BfsuolLogger.data("管理员状态修改，修改对象：",bu.getUserName());	
				return MessageJson.success("更改成功");
			}
	}
	
	@SecDelete
	@RequestMapping("/delete/{id}")
	public @ResponseBody
	MessageJson delete(@PathVariable("id") Long id) {
		String message = "";
		// 清空角色关联
		if(this.removeRole(id)!=null){
			message += this.removeRole(id);
		}
		// 清空用户组关联
		if(this.removeGroup(id)!=null){
			message += this.removeGroup(id);
		}
		
		if (StringUtils.isBlank(message)) {//是否有错误反馈
			baseUserService.removeById(id);
			
			// 删除用户权限后刷新菜单缓存
			//SecurityContext.reloadRoleMenus();
			
			return MessageJson.information("成功删除1条");
		} else {
			throw new ValidationException(message);
		}
	}
	@SecDelete
	@RequestMapping("/delete")
	public @ResponseBody
	MessageJson delete(@RequestParam("ids") Long[] ids) {
		if (ids == null || ids.length == 0) {
			return MessageJson.error("没有删除");
		}
		String message = "";
		for (Long id : ids) {
			message += this.removeRole(id);// 清空角色关联
			message += this.removeGroup(id);// 清空用户组关联
			baseUserService.removeById(id);
		}

		// 删除用户权限后刷新菜单缓存
		//SecurityContext.reloadRoleMenus();
		
		if (StringUtils.isBlank(message)) {//是否有错误反馈
			return MessageJson.information("成功删除" + ids.length + "条");
		} else {
			throw new ValidationException(message);
		}
	}

	/**
	 * 分类用户组列表
	 * @param model
	 * @return
	 */
	@SecFunction(title="用户组设置",code="groupList")
	@RequestMapping("/groupinput/{id}")
	public ModelAndView groupList(@PathVariable("id") Long id,Model model){
		List<Group> groupAll = groupService.findAllIsEnabledGroup();
		Collection<Group> groupChoosed = new ArrayList<Group>();
		List<GroupDTO> groupDTOList = new ArrayList<GroupDTO>();
		
		if(id!=null){
			BaseUser bu = baseUserService.getById(id);
			if(bu!=null&&bu.getGroups()!=null&&bu.getGroups().size()>0){
				groupChoosed = bu.getGroups();// 已选中的用户组
				groupAll.removeAll(bu.getGroups());// 从全部用户组中排除已选中的用户组
			}
		}
		Long[] ids=new Long[200];
		int i=0;
		for(Group g:groupChoosed){
			ids[i]=g.getId();
			i++;
		}
		for(Group group:groupChoosed){
			groupDTOList.add(new GroupDTO(2, group));
		}
		for(Group group:groupAll){
			groupDTOList.add(new GroupDTO(1, group));
		}
		model.addAttribute("userId", id);
		
		model.addAttribute("ids", ids);
//		model.addAttribute("groupList", groupAll);
		model.addAttribute("groupDTOList", groupDTOList);

		ModelAndView modelAndView = new ModelAndView();
		modelAndView.setViewName(getViewNamedPath("groupinput"));
		return modelAndView;
	}
	
	/**
	 * 给账户分配用户组
	 * @param ids
	 * @return
	 */
	@SecFunction(title="用户组设置",code="groupList")
	@RequestMapping("/grouptouser")
	public @ResponseBody MessageJson groupUser(
			@RequestParam(value = "ids", required = false) Long[] ids,
			@RequestParam(value = "userId") Long userId) {
		if(ids==null||ids.length<1){
			throw new ValidationException("请选择要添加的用户组");
		}
		if(userId==null){
			throw new ValidationException("获取不到该账户ID");
		}
		
		BaseUser bu = baseUserService.getById(userId);
		Collection<Role> roleOld = bu.getRoles(); // 用户原有的角色关联关系
		
		// 清空用户组原有的关联
		String groupMessage = this.removeGroup(userId);
		
		if(groupMessage!=null){// 清空失败返回信息
			throw new ValidationException(groupMessage);
		}
		
		// 添加新的用户组
		for(Long id:ids){
			Group group = groupService.getById(id);
			bu.addGroup(group);
		}
		
		// 执行增加或删除组操作，并刷新缓存
		String message = baseUserService.addOrDelGroup(userId, roleOld, baseUserService.canChooseRoleList(userId, bu.getGroups()));
		
		if(!"ok".equals(message)){
			throw new ValidationException(message);
		}
		
		return MessageJson.success("保存成功");
	}
	
	/**
	 * 清空用户组group的关联
	 * @param userId
	 */
	public String removeGroup(Long userId) {
		if (userId == null) {
			return "获取用户ID失败";
		}

		BaseUser bu = baseUserService.getById(userId);
		if (bu == null) {
			return "获取原有用户组信息失败";
		}

		List<Group> groupl = new ArrayList<Group>();

		if (bu.getGroups() != null && bu.getGroups().size() > 0) {
			for (Group group : bu.getGroups()) {// 将collection转换为list
				groupl.add(group);
			}
			for (int i = 0; i < groupl.size(); i++) {// 如果用户与组有关联,先清空关联
				bu.removeGroup(groupl.get(i));
			}

			baseUserService.updateById(bu);

		}

		return null;
	}
	
	/**
	 * 清空用户组role的关联
	 * @param userId
	 */
	public String removeRole(Long userId) {
		if (userId == null) {
			return "获取用户ID失败";
		}

		BaseUser bu = baseUserService.getById(userId);
		if (bu == null) {
			return "获取原有角色信息失败";
		}

		List<Role> rolel = new ArrayList<Role>();

		if (bu.getRoles() != null && bu.getRoles().size() > 0) {
			for (Role role : bu.getRoles()) {// 将collection转换为list
				rolel.add(role);
			}
			for (int i = 0; i < rolel.size(); i++) {// 如果用户与组有关联,先清空关联
				bu.removeRole(rolel.get(i));
			}

			baseUserService.updateById(bu);
		}

		return null;
	}
	
	/**
	 * 重置密码
	 * @param id
	 * @return
	 */
	@RequestMapping("/resetPwd/{id}")
	public @ResponseBody  MessageJson resetPwd(@PathVariable("id") Long id) {
		BaseUser bu = baseUserService.getById(id);
		if(bu.getLoginName().equals(this.getLoginInfo().getLoginName())){
			return MessageJson.fail("不能重置当前登陆的账号密码");
		}else{
			baseUserService.resetPwd(id);
			BfsuolLogger.data("用户密码重置，重置对象：",bu.getUserName());	
			return MessageJson.success("更改成功");
		}
	}
}
